iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
Modern Web

Rails,我要進來囉系列 第 16

第十六天:初探 Rails7 預設的 importmap,結果慘不忍睹…?!

  • 分享至 

  • xImage
  •  

開場白

鼬~~哩賀,我是寫程式的山姆老弟,昨天跟大家一起用 webpacker 安裝、打包並使用了 fontawesomeaxios 的 JS 第三方套件,前幾天也有研究了 Asset Pipeline,可以說是把 Rails 歷代的前端工具都試用過了,今天我們來試試看最新 Rails 7 所預設的 importmap,一個不同於 webpacker 的 JS 解決方案

因為 importmap 在 RailsGuide 還沒出文件,我們就先參考 Github 上的資訊,再加上自己做點實驗來驗證概念,夠夠~

創一個新的實驗用專案

  1. 確認版本 $ rails —-version

    Rails 7.0.4
    

    我實驗用的是 Rails 7.0.4 版

  2. $ rails new test_importmap

研究一下 Rails7 的專案結構

https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day16-1.png

  1. Gemfile 安裝的 gem 有幾個新面孔:

    ...
    
    # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
    gem "sprockets-rails"
    
    # Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
    gem "importmap-rails"
    
    # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
    gem "turbo-rails"
    
    # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
    gem "stimulus-rails"
    
    ...
    
    1. sprocket-rails: 就是 Asset Pipeline,之前都是直接埋在 rails 裡,只是這次變成預設選配,也就是你可以選擇把 Asset Pipeline 取消掉,改用別的 CSS / JS 打包方式
    2. importmap-rails: 這就是今天的研究重點了,看看跟 webpacker 用起來有什麼不一樣
    3. turbo-rails: 目前還沒研究到 turbo,只知道有個 hotwireturbo 好像有點關係,但不知道差別,之後要研究應該會跟舊版的 turbolinks 一起研究
    4. stimulus-rails: 我有偷看了幾位大神在 YT 試用的影片,感覺是個類似 ReactVue 的使用方式,目前看起來我覺得沒有很喜歡,不是很直覺,要用這種方式,我乾脆就直接用 React 還比較好維護
  2. app/views/layouts/application.html.erb 的 js helper method,從 javascript_pack_tag,變成了 javascript_importmap_tags;而 CSS 依舊是預設由 Asset Pipeline 來處理,所以使用 stylesheet_link_tag

    <!DOCTYPE html>
    <html>
      <head>
        <title>TestImportmap</title>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <%= csrf_meta_tags %>
        <%= csp_meta_tag %>
    
        <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
        <%= javascript_importmap_tags %>
      </head>
    
      <body>
        <%= yield %>
      </body>
    </html>
    
  3. app/javascript 資料夾底下沒有 packs 了,改成 controllers,這應該是 stimulus-rails 的結構

  4. 外層沒有 package.json 了,改成在 config/importmap.rb

    # Pin npm packages by running ./bin/importmap
    
    pin "application", preload: true
    pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
    pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
    pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
    pin_all_from "app/javascript/controllers", under: "controllers"
    

建個實驗場域

  1. 新增個頁面 $ rails g controller home index

  2. 把新頁面變成首頁

    # config/routes.rb
    Rails.application.routes.draw do
      root 'home#index'
    end
    

試試用 importmap 來使用 bootstrap 5

  1. $ ./bin/importmap pin bootstrap jquery

    Pinning "bootstrap" to https://ga.jspm.io/npm:bootstrap@5.2.1/dist/js/bootstrap.esm.js
    Pinning "@popperjs/core" to https://ga.jspm.io/npm:@popperjs/core@2.11.6/lib/index.js
    Pinning "jquery" to https://ga.jspm.io/npm:jquery@3.6.1/dist/jquery.js
    

    是直接使用 CDN 的方式安裝,會在 config/importmap.rb 新增以下幾行

    # config/importmap.rb
    
    pin "bootstrap", to: "https://ga.jspm.io/npm:bootstrap@5.2.1/dist/js/bootstrap.esm.js"
    pin "@popperjs/core", to: "https://ga.jspm.io/npm:@popperjs/core@2.11.6/lib/index.js"
    pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.1/dist/jquery.js"
    
  2. app/javascript/application.js 引用 bootstrap

    // app/javascript/application.js
    ...
    import 'bootstrap'
    import 'jquery'
    import '@popperjs/core'
    
  3. 啟動 $ rails s,打開 127.0.0.1:3000,檢查一下 header,確認是有引用 bootstrap 和相依套件 popper,這樣就算使用 importmap 來安裝 bootstrap,是不是很簡單啊? 才怪…

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day16-2.png

  4. 剛才完成的只有 bootstrap 的 JS 部分而已,如果要使用 bootstrap 的 CSS 部分,還是要回歸 Asset Pipeline,心裡 OS: bootstrap 最重要的就是 CSS 啊,怎麼還是那麼麻煩!

    所以要在 Gemfile 新增 gem 'bootstrap',同時把 sass 放回來,Rails 7 預設是不安裝 sass 的,並執行 $ bundle install

    # Gemfile
    
    ...
    # Use Sass to process CSS
    gem "sassc-rails"
    # Use Bootstrap
    gem 'bootstrap'
    
  5. 為了套用 sass,把 app/assets/stylesheets/application.css 改名為 app/assets/stylesheets/application.scss,並新增 @import 'bootstrap'

    /*
     * This is a manifest file that'll be compiled into application.css, which will include all the files
     * listed below.
     *
     * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
     * vendor/assets/stylesheets directory can be referenced here using a relative path.
     *
     * You're free to add application-wide styles to this file and they'll appear at the bottom of the
     * compiled file so the styles you add here take precedence over styles defined in any other CSS
     * files in this directory. Styles in this file should be added after the last require_* statement.
     * It is generally better to create a new file per style scope.
     *
     *= require_tree .
     *= require_self
     */
    
     @import 'bootstrap';
    
  6. app/views/home/index.html.erb 新增幾個 bootstrap 元件:nav bar、dropdown button、tooltip button,還有 bootstrap style 的 p tag

    <!-- app/views/home/index.html.erb -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark" aria-label="Ninth navbar example">
      <div class="container-xl">
        <a class="navbar-brand" href="#">Container XL</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample07XL" aria-controls="navbarsExample07XL" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
    
        <div class="collapse navbar-collapse" id="navbarsExample07XL">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled">Disabled</a>
            </li>
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</a>
              <ul class="dropdown-menu">
                <li><a class="dropdown-item" href="#">Action</a></li>
                <li><a class="dropdown-item" href="#">Another action</a></li>
                <li><a class="dropdown-item" href="#">Something else here</a></li>
              </ul>
            </li>
          </ul>
          <form role="search">
            <input class="form-control" type="search" placeholder="Search" aria-label="Search">
          </form>
        </div>
      </div>
    </nav>
    
    <h1>Home#index</h1>
    
    <button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-placement="top">Tooltip on top</button>
    
    <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
      Dropend button
    </button>
    
    <%= content_tag(:div, class: 'container') do %>
        <p class="bg-dark text-light">Find me in app/views/home/index.html.erb</p>
    <% end %>
    
  7. 啟動 $ rails s,打開 127.0.0.1:3000,檢查一下,會發現 CSS 部分是正常的,但 JS 的運作有問題,只有 navbar 的展開是正常,其他像是 dropdown、tooltips 都是會報錯的

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day16-3.png

嘗試修復

我後來看了大神的 YT 教學,終於修好了,真的是傻眼,跟我一起看一下怎麼修的吧

  1. config/importmap.rb 要修一下,把 @popperjs/core 的 to 的路徑修正

    pin "bootstrap", to: "https://ga.jspm.io/npm:bootstrap@5.2.1/dist/js/bootstrap.esm.js"
    - pin "@popperjs/core", to: "https://ga.jspm.io/npm:@popperjs/core@2.11.6/lib/index.js"
    + pin "@popperjs/core", to: "https://unpkg.com/@popperjs/core@2.11.6/dist/esm/index.js"
    

    我就問,到底誰會知道要這樣改!!!?

    然後重新啟動、重新整理之後, navbar 的 dropdown 就好了,WTF

    https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day16-4.png

    但下面的 tooltips 和 dropdown button 還是不能正常運作,我不懂,我真的不懂到底是發生什麼事了 Q_Q

結論

恩… 試用 importmap 之後,讓我覺得非常傻眼,這些奇怪的 bug 遇到了都不知道怎麼修,到底誰會知道要改 library 的來源處,總之我應該之後會嘗試用別的方法,我放棄 importmap 了…,我們明天見…


上一篇
第十五天:用 webpacker 使用第三方前端套件
下一篇
第十七天:在 Rails 7 用 jsbundling + webpack 安裝並使用 bootstrap
系列文
Rails,我要進來囉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
Robert Chang
iT邦新手 3 級 ‧ 2022-10-01 12:32:08

Hi,
剛好最近公司的新專案是使用 Rails 7,可以透過直接下載 bootstrap 的 min.css

並且手動放進 assets/stylesheets,之後就會被 applicaiton.html.erb 內的 stylesheet_link_tag 帶進來。

若是要把 css 整理到別的資料夾內,記得在 config/intializers/asset.rbRails.application.config.assets.paths << 加入你想要的路徑 ( 通常用會 Rails.root.join 起手 )

因為沒有了 node_mudules 所以確實一開始會有點不習慣,但這種要用什麼裝什麼的感覺其實很讚

Sam iT邦新手 4 級 ‧ 2022-10-02 09:51:24 檢舉

感謝分享~ 我之後再多用幾個專案來玩玩看 importmap

0
twbcs
iT邦新手 5 級 ‧ 2022-12-24 14:32:31

tooltips 需要增加 code 啟用

import "@popperjs/core"

document.addEventListener("turbo:load", () => {
  const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
  const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
  const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
  const popoverList = popoverTriggerList.map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
})

至於 dropdown button 我沒遇到問題

我要留言

立即登入留言